package logic

import (
	"cloud-disk/global/db"
	"cloud-disk/global/define"
	"cloud-disk/model/entity"
	"cloud-disk/model/response"
	"cloud-disk/mq"
	"encoding/json"
	"errors"
	"log"
)

func FileUploadLogic(repo entity.RepositoryPool) error {
	res := db.DB().Create(&repo)
	err := res.Error
	affect := res.RowsAffected
	if err != nil {
		log.Println(err)
		return errors.New("unknown error")
	}
	if affect <= 0 {
		return errors.New("record already exist")
	}
	return nil
}

func IsExistInRepoPool(fhash string) (string, bool, error) {
	var cnt int64
	var identity string
	err := db.DB().Model(&entity.RepositoryPool{}).Select("identity").Where("hash=?", fhash).Limit(1).Count(&cnt).Scan(&identity).Error
	if err != nil {
		log.Println(err)
		return "", true, errors.New("unknown err")
	}
	if cnt == 0 {
		return "", false, nil
	}
	return identity, true, nil
}

// 需要参数
// 1. id
// 返回参数
// 1. size
// 2. include file number
func DirInfoLogic(id int) (*response.DirInfo, error) {
	type LeftRes struct {
		RepositoryIdentity string
		Type               string
	}
	lefres := []LeftRes{}
	left := db.DB().Debug().
		Select("repository_identity, type").
		Table("user_repository as ur,(select @pv := ?) initialisation", id).
		Where("(find_in_set(ur.parent_id,@pv) > 0 and @pv := concat(@pv, ',', ur.id))").
		Scan(&lefres)
	if left.Error != nil {
		log.Println(left.Error)
		return nil, errors.New("unknown err")
	}
	var fcnt, dcnt int
	for i := 0; i < len(lefres); i++ {
		if lefres[i].Type == "file" {
			fcnt++
		}
		if lefres[i].Type == "dir" {
			dcnt++
		}
	}
	var size float64
	err := db.DB().Debug().Select("sum(rp.size)").Table("(?) as ur", left).Joins("left join repository_pool as rp on  ur.repository_identity=rp.identity").Scan(&size).Error
	if err != nil {
		log.Println(left.Error)
		return nil, errors.New("size statistic unknown err")
	}
	resp := response.DirInfo{
		TotalSize: int(size),
		DirCount:  dcnt,
		FileCount: fcnt,
	}
	return &resp, nil

	//select id from (select * from user_repository) user_repository, (select @pv := ? ) initialisation where   (find_in_set(parent_id, @pv) > 0 and @pv := concat(@pv, ',', id)) or id=?
}

func FileInfoLogic(id int) (int, error) {
	sub := db.DB().Table("user_repository").Select("repository_identity").Where("id=?", id)
	var size int
	err := db.DB().Select("size").Table("repository_pool").Where("identity=(?)", sub).Scan(&size).Error
	if err != nil {
		return -1, errors.New("info get error")
	}
	return size, nil
}

func UpdateFileStoreWayLogic(fhash, location string, way string) error {
	err := db.DB().Model(&entity.RepositoryPool{}).Where("hash=?", fhash).Updates(entity.RepositoryPool{Location: location, StoreWay: way}).Error
	if err != nil {
		return errors.New("change store way fail")
	}
	return nil
}

func PublishStoreMsgLogic(msg mq.TransferMessage) error {
	conf := define.Conf.RabbitMQ
	msgBytes, err := json.Marshal(msg)
	if err != nil {
		log.Println(err)
		return errors.New("parameter error")
	}
	ok := mq.Publish(conf.TransferExchangeName, conf.TransOssRoutingKey, msgBytes)
	if !ok {
		return errors.New("publish error")
	}
	return nil
}

func PublishRemoveChunksLogic(fpath string) error {
	conf := define.Conf.RabbitMQ
	ok := mq.Publish(conf.RemoveExchangeName, conf.RemoveChunkRoutingKey, []byte(fpath))
	if !ok {
		return errors.New("publish error")
	}
	return nil
}
